package com.agilestudio.ifinance.web.account;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import com.agilestudio.ifinance.entity.account.Menu;
import com.agilestudio.ifinance.entity.account.Role;
import com.agilestudio.ifinance.entity.account.User;
import com.agilestudio.ifinance.web.AbstractController;
import com.agilestudio.modules.orm.Page;
import com.agilestudio.modules.orm.PropertyFilter;

@Controller
@RequestMapping(value = "user")
public class UserController extends AbstractController {

	@RequestMapping(value = "list", method = RequestMethod.GET)
	public String list(Map<String, Object> map) {
		log.info("RequestMethod.GET user list...");
		initMenus(map);
		return "user/list";
	}

	@RequestMapping(value = "add", method = RequestMethod.GET)
	public ModelAndView add(Map<String, Object> map) {
		log.info("RequestMethod.GET user add...");
		initMenus(map);
		ModelAndView mav = new ModelAndView("user/add");
		User user = new User();
		initView(mav, user);
		return mav;
	}

	@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
	public ModelAndView edit(Map<String, Object> map, @PathVariable String id) {
		log.info("RequestMethod.GET user edit..." + id);
		initMenus(map);
		ModelAndView mav = new ModelAndView("user/edit");
		User user = accountService.getUser(Long.valueOf(id));
		initView(mav, user);
		return mav;
	}

	// @RequestMapping(value = "list", method = RequestMethod.POST)
	// public @ResponseBody
	// Map<String, Object> list(WebRequest wr, FlexiGrid<User> flexiGrid) {
	// for (Map.Entry<String, String[]> s : wr.getParameterMap().entrySet()) {
	// log.info("list 0000------" + s.getKey() + ":" + s.getValue()[0]);
	// }
	// Page<User> page = flexiGrid;
	// log.info("list ######## = " + flexiGrid);
	// List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
	// if (flexiGrid != null && flexiGrid.getAddparams() != null) {
	// for (int i = 0; i < flexiGrid.getAddparams().size(); i++) {
	// log.info("list 22222----------"
	// + flexiGrid.getAddparams().get(i).toString());
	// filters.add(new PropertyFilter("LIKE", "S", flexiGrid
	// .getAddparams().get(i).getName(), flexiGrid
	// .getAddparams().get(i).getValue().toString()));
	// }
	// }
	// page = accountService.searchUser(flexiGrid, filters);
	// List<User> users = flexiGrid.getResult();
	// List<Map<String, ? extends Object>> rows = new ArrayList<Map<String, ?
	// extends Object>>();
	// for (User user : users) {
	// Map<String, Object> node = new HashMap<String, Object>();
	// List<String> metadata = new ArrayList<String>();
	// node.put("id", user.getId());
	// metadata.add(user.getId().toString());
	// metadata.add(user.getLoginName());
	// metadata.add(user.getName());
	// metadata.add(user.getEmail());
	// node.put("cell", metadata);
	// rows.add(node);
	// }
	// Map<String, Object> map = new HashMap<String, Object>();
	// map.put("page", page.getPageNo());
	// map.put("rows", rows);
	// map.put("total", page.getTotalCount());
	// return map;
	// }

	@RequestMapping(value = "list", method = RequestMethod.POST)
	public String list(Map<String, Object> map, WebRequest wr, Page<User> page) {
		for (Map.Entry<String, String[]> s : wr.getParameterMap().entrySet()) {
			log.info("list 0000------" + s.getKey() + ":"
					+ ToStringBuilder.reflectionToString(s.getValue()) + ":"
					+ s.getValue().length);
		}
		log.info("list ######## = " + page);
		initMenus(map);
		List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
		page = accountService.searchUser(page, filters);
		map.put("page", page);
		return "user/list";
	}

	private void initView(ModelAndView mav, User user) {
		user.setRids(user.getRoleIds());
		List<Role> roles = accountService.getRoles();
		mav.addObject("user", user);
		mav.addObject("roles", roles);
		log.info("user to be displayed : " + user.getRids().size() + ";"
				+ user.getRids());
		log.info("roles to be displayed : " + roles.size());
	}

	@RequestMapping(value = "save", method = RequestMethod.POST)
	public ModelAndView save(Map<String, Object> map, @Valid User user,
			BindingResult result) {
		initMenus(map);
		log.info("save = " + user.toString());
		for (FieldError fe : result.getFieldErrors()) {
			log.info("save error FieldError= " + fe.getField() + ";"
					+ fe.getCode() + ";" + fe.getDefaultMessage());
		}
		ModelAndView mav = new ModelAndView("user/edit");
		if (user.getId() == null) {
			if (result.hasErrors()) {
				mav.setViewName("user/add");
			} else {
				user.getRoles().clear();
				if (user.getRids() != null) {
					for (Long id : user.getRids()) {
						if (id != null) {
							user.getRoles().add(accountService.getRole(id));
						}
					}
				}
				accountService.saveUser(user);
			}
			// mav.addObject("user", user);
			initView(mav, user);
		} else {
			User u = accountService.getUser(user.getId());
			u.setLoginName(user.getLoginName());
			u.setPassword(user.getPassword());
			u.setName(user.getName());
			u.setCode(user.getCode());
			u.setEmail(user.getEmail());
			u.setSex(user.getSex());
			u.setBirthDate(user.getBirthDate());
			u.setStatus(user.getStatus());
			if (!result.hasErrors()) {
				u.getRoles().clear();
				if (user.getRids() != null) {
					for (Long id : user.getRids()) {
						if (id != null) {
							u.getRoles().add(accountService.getRole(id));
						}
					}
				}
				accountService.saveUser(u);
			}
			// mav.addObject("user", u);
			initView(mav, u);
		}
		return mav;

	}

	@RequestMapping(value = "load", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, ? extends Object> load(@RequestParam("id") String id) {
		log.info("load = " + id);
		User user = accountService.getUser(Long.valueOf(id));
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", user.getId());
		map.put("loginName", user.getLoginName());
		map.put("name", user.getName());
		map.put("email", user.getEmail());
		log.info("load = " + map);
		return map;
	}

	@RequestMapping(value = "delete", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, String> delete(@RequestParam("id") String id) {
		log.info("delete1 = " + id);
		User user = accountService.getUser(Long.valueOf(id));
		user.setEmail("disabled@asdf.com");
		accountService.saveUser(user);
		Map<String, String> map = new HashMap<String, String>();
		map.put("info", "success");
		return map;
	}

	@RequestMapping(value = "loadUserRole", method = RequestMethod.POST)
	public ModelAndView loadUserRole(@RequestParam("id") Long id) { //
		Map<Role, String> fineRoles = new HashMap<Role, String>();
		// List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
		List<Role> roles = accountService.getRoles();
		User user = accountService.getUser(id);
		List<Role> userRoles = user.getRoles();
		for (Role role : roles) {
			if (inRole(role, userRoles))
				fineRoles.put(role, "1");
			else
				fineRoles.put(role, "0");
		}
		ModelAndView mav = new ModelAndView("user/_userrole");
		mav.addObject("roles", fineRoles);
		return mav;
	}

	@RequestMapping(value = "saveUserRole", method = RequestMethod.POST)
	public ModelAndView saveUserRole(WebRequest wr,
			@RequestParam("id") Long id, @RequestParam("ids") String ids) {
		for (Map.Entry<String, String[]> s : wr.getParameterMap().entrySet()) {
			log.info("saveUserRole------" + s.getKey() + ":" + s.getValue()[0]);
		}
		String[] idArray = ids.split(",");
		User user = accountService.getUser(id);
		user.getRoles().clear();
		for (int i = 0; i < idArray.length; i++) {
			log.info("--------" + idArray[i]);
			if (StringUtils.isNotEmpty(idArray[i])) {
				user.getRoles().add(
						accountService.getRole(Long.valueOf(idArray[i])));
			}
		}
		accountService.saveUser(user);
		ModelAndView mav = loadUserRole(id);
		return mav;
	}

	private boolean inRole(Role role, List<Role> roles) {
		for (Role role2 : roles) {
			if (role2.getId() == role.getId())
				return true;
		}
		return false;
	}

	@RequestMapping(value = "loadUserMenu", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, Object> loadUserMenu(@RequestParam("sortname") String sortname,
			@RequestParam("sortorder") String sortorder) {
		log.info("loadUserMenus..." + "sortname=" + sortname + ";sortorder="
				+ sortorder);
		List<Map<String, ? extends Object>> rows = new ArrayList<Map<String, ? extends Object>>();
		List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
		List<Menu> menus = accountService.searchMenu(filters);
		for (Menu menu : menus) {
			Map<String, Object> node = new HashMap<String, Object>();
			List<String> metadata = new ArrayList<String>();
			node.put("id", menu.getId());
			metadata.add(menu.getId().toString());
			metadata.add(menu.getCode());
			metadata.add(menu.getName());
			metadata.add(menu.getUrl());
			metadata.add(String.valueOf(menu.isLeaf()));
			node.put("cell", metadata);
			rows.add(node);
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("rows", rows);
		map.put("total", menus.size());
		return map;
	}
}
